<?php

namespace app\common\model;

use think\Model;
use think\Loader;
use think\Log;
use think\Db;


Loader::import('WxPay.WxPay', EXTEND_PATH, '.Api.php');
require_once EXTEND_PATH . "WxPay/WxPay.Config.php";

class Pay extends Base
{


    protected $redata;

    public function _initialize()
    {
        $this->redata = ['content' => '', "status" => 0, 'msg' => ''];
    }


    /**
     * 快捷方法 返回出错信息
     */
    protected function err($msg)
    {
        $this->redata['msg'] = $msg;
        $this->redata['status'] = 0;
        return $this->redata;
    }

    /**
     * 快捷方法 返回成功
     */
    protected function suc($data = '')
    {
        $this->redata['content'] = $data;
        $this->redata['status'] = 1;
        return $this->redata;
    }


    /**
     * 支付
     * $cid 用户编码
     * $money 支付金额
     * $moneyType 1-收入 2-支出
     * $payType 支付方式 1-钱包 2-微信 4-后台支付
     * $orderSrc  流水来源    1-交易订单 2-购买月卡 3-提现申请 4-后台操作 5-充值 6-提现失败 7-点亮好xx 8-购买年卡
     * $orderId 订单编码，可以为空
     *
     * $res status 1-成功 0-失败
     *
     */
    public function pay ($cid = 0, $money = 0, $moneyType = 0, $payType = 0, $orderSrc = 0, $orderId = 0,$userCouponId=0)
    {
        // 判断参数合法
        $user = model('user')->where(['id' => $cid])->find();
        if (empty($user)) {
            return $this->err('用户编码有误！');
        }

        if ($money <= 0) {
            return $this->err('支付金额不能小于0！');
        }

        if ($moneyType != 1 && $moneyType != 2) {
            return $this->err('收支状态有误！');
        }
        if ($payType != 1 && $payType != 2  && $payType != 4) {
            return $this->err('付款方式有误！');
        }
        if ($orderSrc != 1 && $orderSrc != 2 && $orderSrc != 3 && $orderSrc != 4 && $orderSrc != 5 && $orderSrc != 6 && $orderSrc != 7 && $orderSrc != 8) {
            return $this->err('流水来源有误！');
        }

        //查询订单类型
        if(!empty($orderId)){
            $order=model('order')->where(['id'=>$orderId])->find();
        }

        if (!empty($userCouponId)) {
            $now=time();
            //查询用户使用的优惠券信息
            $uc_res=model('user_coupon')->where(['id'=>$userCouponId])->find();
            $overTime=strtotime($uc_res['overTime']);
            if($overTime<$now){
                return $this->err('优惠券已过期！');
            }
            if($uc_res['status']==2){
                return  $this->err('优惠券已被使用过！');
            }
            //查询优惠券的使用要求
            $c_res=model('coupon')->where(['id'=>$uc_res['couponId']])->find();
            //判断是否达到使用需求
            if($money<$c_res['fullAmount']){
                return  $this->err('没有满足使用需求！');
            }
            if($c_res['status']==0){
                return  $this->err('该优惠券已被禁用！');
            }
            $money=$money-$c_res['reduceAmount'];
        }

        // 判断支付方式
        switch ($payType) {
            case 1:
                if ($user['money'] < $money) {
                    return $this->err('钱包余额不足，请先充值！');
                }

                $user['money'] = $user['money'] - $money;
                $u_data = [
                    'id' => $cid,
                    'money' => $user['money']
                ];

                $u_res =model('user')->editData($u_data, $u_data['id']);

                if (!$u_res) {
                    return $this->err('钱包操作有误！');
                }

                if (!empty($userCouponId)) {
                    //付款成功后改变订单状态
                    $order_data = [
                        'id' => $orderId,
                        'totalAmount' => $money,
                        'couponAmount'=>$c_res['reduceAmount'],
                        'paymentStatus'=>1,
                        'isUseCoupon'=>1,
                        'userCouponId'=>$userCouponId,
                        'payTime'=>createTime(),
                    ];
                }
                else{
                    $order_data = [
                        'id' => $orderId,
                        'paymentStatus'=>1,
                        'payTime'=>createTime(),
                    ];
                }

                //更新订单状态
               $order_res= model('order')->editData($order_data, $order_data['id']);
                if (!$order_res) {
                    return $this->err('更新订单失败');
                }

                //更新后修改状态
               model('order')-> updateStatus($order['employeeId'],$order['workId'],$order['type']);

                break;
            case 4:
                break;
            default:
                return $this->err('支付方式有误！');
                break;

        }
        if ($orderId) {
            $order_data = [
                'id' => $orderId,
                'paymentStatus' => 1
            ];
            model('order')->editData($order_data, $order_data['id']);
        }
        $moneySn = createOrderCode('ZJ');
        // 插入订单流水
        $l_data = [
            'targetId' => $cid,
            'orderId' => $orderId,
            'orderSrc' => $orderSrc,
            'moneyType' => $moneyType,
            'moneySn' => $moneySn,
            'money' => $money,
            'leftMoney' => $user['money'],
            'payType' => $payType,
            'createTime' => createTime()
        ];
        $l_res = model('user_money_log')->editData($l_data);
        if($userCouponId){
            $uc_data=[
                'id'=>$userCouponId,
                'status'=>2
            ];
          model('user_coupon')->where(['id'=>$userCouponId])->update($uc_data);
        }
        if (!$l_res) {
            return $this->err('订单流水有误！');
        }else{
            return $this->suc($l_res);
        }
    }

    /**
     * 预支付订单
     */
    public function makeWxPreOrder($orderId, $openid, $ucId = 0)
    {
        //传递过来的参数为订单商品总价格
        /**
         *
         * 统一下单，WxPayUnifiedOrder中out_trade_no、body、total_fee、trade_type必填
         * appid、mchid、spbill_create_ip、nonce_str不需要填入
         * @param WxPayUnifiedOrder $inputObj
         * @param int $timeOut
         * @throws WxPayException
         * @return 成功时返回，其他抛异常
         */
        $orderId ? true : $this->err('缺少订单主键！');
        $openid ? true : $this->err('缺少openid！');

        // 订单逻辑
        $field = ['id, type, orderAmount, paymentStatus, cancelStatus, orderSn'];

        $order = model('order')->field($field)->where(['id' => $orderId])->find();

        if ($order['paymentStatus'] == 1) {
            return $this->err('订单已支付！');
        }
        if ($order['cancelStatus'] == 1) {
            return $this->err('订单已被取消！');
        }
        $type = '雇佣阿姨';
        // 启动事务
        Db::startTrans();
        try {
            switch ($order['type']) {
                //订单类型  1-雇佣阿姨 2-雇主购买月卡 3-阿姨购买月卡 4-好雇主认证 5-好阿姨认证
                case 1:
                    $type = '雇佣阿姨';
                    break;
                case 2:
                    $type = '雇主购买月卡';
                    break;
                case 3:
                    $type = '阿姨购买月卡';
                    break;
                case 4:
                    $type = '好雇主认证';
                    break;
                case 5:
                    $type = '好阿姨认证';
                    break;
                case 6:
                    $type = '雇主充值';
                    break;
                case 7:
                    $type = '阿姨充值';
                    break;
                case 8:
                    $type = '雇主购买年卡';
                    break;
                case 9:
                    $type = '阿姨购买年卡';
                    break;
                default:
                    return $this->err('订单类型错误！');
                    break;
            }
            // 优惠金额
            $couponAmount = model('coupon')->useCoupon($ucId, $order['orderAmount']);
            if (!$couponAmount['status']) {
                return $this->err($couponAmount['msg']);
            }
 //新增代码开始
          if($ucId) {
              $uc_data = [
                  'id' => $ucId,
                  'status' =>1
              ];
              model('user_coupon')->editData($uc_data, $uc_data['id']);
          }
//新增代码结束
            // 订单实际价格
            $amount = subFloat($order['orderAmount'], $couponAmount['content']);

            //写入订单

            $o_res = [
                'userCouponId' => $ucId,
                'totalAmount' => $amount,
                'couponAmount' => $couponAmount['content'],
                'payType' => 2
            ];

            //是否使用优惠券
            $couponAmount['content'] ? $o_res['isUseCoupon'] = 1 : $o_res['isUseCoupon'] = 0;

            model('order')->editData($o_res, $orderId);

            $wxOrderData = new \WxPayUnifiedOrder();
            //唯一订单号
            $wxOrderData->SetOut_trade_no($order['orderSn']);
            //代表JSAPI模式，不要修改，公众号支付，H5，小程序都是这个
            $wxOrderData->SetTrade_type('JSAPI');
            //价格，单位为分
            $wxOrderData->SetTotal_fee((int)($amount * 100));
            //商品简介
            $wxOrderData->SetBody($type);
            //使用小程序用户的openid
            $wxOrderData->SetOpenid($openid);
            //异步回调验证路径，开发者自定义
            $wxOrderData->SetNotify_url('http://api.guyig.com/index/pay/wxPayReturn');
            //这个是我又封装的一个生成签名的方法
            $order = $this->getPaySignature($wxOrderData);
            if ($order) {
                // 提交事务
                Db::commit();
                return $this->suc($order);
            } else {
                // 回滚事务
                Db::rollback();
                return $this->err('发起失败！');
            }

        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return $this->err('发起失败！');
        }

    }

    // 获取与支付信息
    private function getPaySignature($wxOrderData)
    {
        $config = new \WxPayConfig();
        $wxOrder = \WxPayApi::unifiedOrder($config, $wxOrderData);
        // 失败时不会返回result_code
        if ($wxOrder['return_code'] != 'SUCCESS' || $wxOrder['result_code'] != 'SUCCESS') {
            Log::record($wxOrder, 'error');
            Log::record('获取预支付订单失败', 'error');//这里为记录异常，根据自己业务选择处理
            return false;
        }
        $signature = $this->sign($wxOrder);
        return $signature;
    }

    //按照文档要求生成签名，传递给小程序，让小程序拉起支付
    private function sign($wxOrder)
    {
        $config = new \WxPayConfig();
        $jsApiPayData = new \WxPayJsApiPay();
        //传入小程序appid
        $jsApiPayData->SetAppid($config->GetAppId());
        //按照文档，要求是字符串类型
        $jsApiPayData->SetTimeStamp((string)time());
        //生成随机字符串
        $rand = md5(time() . mt_rand(0, 1000));
        $jsApiPayData->SetNonceStr($rand);
        //拼接prepay_id，要注意拼接
        $jsApiPayData->SetPackage('prepay_id=' . $wxOrder['prepay_id']);
        //签名方式md5
        $jsApiPayData->SetSignType('md5');
        //然后调用sdk自带的MakeSign方法生成签名
        $sign = $jsApiPayData->MakeSign($config);
        //然后在使用sdk自带方法获取到上面的我们赋值到成员属性生成的数组
        $rawValues = $jsApiPayData->GetValues();
        //然后我们在数组上加上生成的签名
        $rawValues['paySign'] = $sign;
        //删除appid，因为返回给客户端没有用，所以消除
        unset($rawValues['appId']);
        //返回
        return $rawValues;
    }

    public function rechargeWxPreOrder($openid,$rechargeMoney,$coc){
        /**
         *
         * 统一下单，WxPayUnifiedOrder中out_trade_no、body、total_fee、trade_type必填
         * appid、mchid、spbill_create_ip、nonce_str不需要填入
         * @param WxPayUnifiedOrder $inputObj
         * @param int $timeOut
         * @throws WxPayException
         * @return 成功时返回，其他抛异常
         */
        $openid ? true : $this->err('缺少openid！');
        $rechargeMoney ? true : $this->err('缺少充值金额！');
        $coc ? true : $this->err('缺少交易编码！');

        // 启动事务
        Db::startTrans();
        try {
            $wxOrderData = new \WxPayUnifiedOrder();
            //唯一订单号
            $wxOrderData->SetOut_trade_no($coc);
            //代表JSAPI模式，不要修改，公众号支付，H5，小程序都是这个
            $wxOrderData->SetTrade_type('JSAPI');
            //价格，单位为分
            $wxOrderData->SetTotal_fee((int)($rechargeMoney * 100));
            //商品简介
            $wxOrderData->SetBody('充值');
            //使用小程序用户的openid
            $wxOrderData->SetOpenid($openid);
            //异步回调验证路径，开发者自定义
            $wxOrderData->SetNotify_url('http://api.guyig.com/index/pay/wxPayReturn');
            //这个是我又封装的一个生成签名的方法
            $order = $this->getPaySignature($wxOrderData);
            if ($order) {
                // 提交事务
                Db::commit();
                return $this->suc($order);
            } else {
                // 回滚事务
                Db::rollback();
                return $this->err('发起失败！');
            }

        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            return $this->err('发起失败！');
        }

    }

}
